package com.test.MyPlugin;


import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemProperties;
import android.serialport.DeviceControlSpd;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;

import androidx.core.app.ActivityCompat;

import com.example.fingerdemo.ConSample;
import com.example.fingerdemo.FingerStatusCode;
import com.example.fingerdemo.UsbApi;
import com.example.fingerdemo.androidbmp;
import com.example.fingerdemo.finger;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class MyPlugin extends CordovaPlugin {

    private Context mContext = null;
    private static final String TAG = "MyPluginFinger";
    UsbApi usbApi = null;
    private int offset = 0;
    private ConSample mConSample;
    private static Handler messageHandler = null;
    public androidbmp mandroidbmp;
    public String bmpfilepath;
    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static final String[] PERMISSIONS_STORAGE = {Manifest.permission.WRITE_EXTERNAL_STORAGE};

    int ret;
    short[] caicai = new short[4];
    byte[] bmpdelete = new byte[256 * 360 + 1078];
    byte[] test = new byte[6];
    String test_byte = new String(test);
    short[] sampleimage = new short[(256 * 360 + 1078) / 2];

    private CallbackContext callbackContext;
//    static {
//        System.loadLibrary("finger");
//    }

    // 插件构造函数
    public MyPlugin() {
        // 加载本地库
        System.loadLibrary("finger");
    }


    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

        Log.d(TAG, "execute:" + action);
        if (action.equals("aaa")) {
            String message = args.getString(0);
            this.aaa(message, callbackContext);
            return true;
        }
        // TODO: 2024/8/18/周日  上电 下电
        if (action.equals("powerOn")) {
            String message = args.getString(0);
            this.powerOn(message, callbackContext);
            return true;
        }
        if (action.equals("powerOff")) {
            String message = args.getString(0);
            this.powerOff(message, callbackContext);
            return true;
        }
        //再就是指纹相关部分的接口了。
        if (action.equals("init")) {
            String message = args.getString(0);
            this.init(message, callbackContext);
            return true;
        }
        if (action.equals("openDev")) {
            String message = args.getString(0);
            this.open(message, callbackContext);
            return true;
        }
        if (action.equals("closeDev")) {
            String message = args.getString(0);
            this.close(message, callbackContext);
            return true;
        }
        //校准
        if (action.equals("calibration")) {
            String message = args.getString(0);
            this.calibration(message, callbackContext);
            return true;
        }
        //采集指纹
        if (action.equals("collect")) {
            String message = args.getString(0);
            this.collect(message, callbackContext);
            return true;
        }
        //连续采集
        if (action.equals("continuousCollect")) {
            String message = args.getString(0);
            this.continuousCollect(message, callbackContext);
            return true;
        }
        //连续采集
        if (action.equals("stopContinuousCollect")) {
            String message = args.getString(0);
            this.stopContinuousCollect(message, callbackContext);
            return true;
        }
        return false;
    }

    private void aaa(String message, CallbackContext callbackContext) {
        //弹框
        Toast.makeText(cordova.getActivity(), "aaa", Toast.LENGTH_LONG).show();
        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void powerOn(String message, CallbackContext callbackContext) {

        // TODO: 2023/03/02/017 上电
        if ("FG80-6762".equals(SystemProperties.get("ro.build.developer"))) {
            initPower6762();
        } else if ("FG80-T7520".equals(SystemProperties.get("ro.build.developer"))) {
            initPowerT7520();
        } else {
            initPower();
        }

        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void powerOff(String message, CallbackContext callbackContext) {

        // TODO: 2023/03/02/017 下电
        if ("FG80-6762".equals(SystemProperties.get("ro.build.developer"))) {
            releaseDMRModule6762();
        } else if ("FG80-T7520".equals(SystemProperties.get("ro.build.developer"))) {
            releaseT7520Module();
        } else {
            releaseDMRModule();
        }

        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void init(String message, CallbackContext callbackContext) {

        // TODO: 2023/03/02/017 初始化
        mContext = cordova.getActivity();
        Log.d(TAG, "init:" + (cordova != null));
        verifyPermission(mContext);
        mandroidbmp = new androidbmp();
        bmpfilepath = Environment.getExternalStorageDirectory().getAbsolutePath();

        Log.d(TAG, "init bmpfilepath:" + bmpfilepath);

        Looper looper = Looper.getMainLooper();
        messageHandler = new MessageHandler(looper);
        usbApi = UsbApi.getInstance(mContext);

        mConSample = new ConSample(cordova.getActivity(), mSampleListener);
        mConSample.start();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ret = usbApi.UsbOpenDevice(mContext);
            Log.d(TAG, "init:" + "UsbOpenDevice = " + (ret == FingerStatusCode.STATUS_OK));
        }

        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    Bitmap bitmap;

    private void open(String message, CallbackContext callbackContext) {
        //String filename = bmpfilepath + "/finger.bmp";
        //String filename_cal = bmpfilepath + "/cal.bmp";
        Log.d(TAG, "open:" + "start");
        // TODO: 2023/03/02/017 打开
        ret = usbApi.UsbOpenDevice(mContext);

        Log.d(TAG, "open:" + "UsbOpenDevice");
        if (ret == FingerStatusCode.STATUS_OK) {
            Log.d(TAG, "open:" + "STATUS_OK");
            if (usbApi.devName != null) {
                //usbApi.devName;
                Log.d(TAG, "open:devName" + usbApi.devName);
            }
            if (usbApi.interfaceName != null) {
                //usbApi.interfaceName;
                Log.d(TAG, "open:interfaceName" + usbApi.interfaceName);
            }
            //  "epCount" + usbApi.epCount
            //  "permit" + //usbApi.permit
            // "filedescription" + usbApi.fd
            Log.d(TAG, "open:epCount" + usbApi.epCount);
            Log.d(TAG, "open:permit" + usbApi.permit);
            Log.d(TAG, "open:filedescription" + usbApi.fd);

            int filedescription = usbApi.fd;
            Log.d(TAG, "open:filedescription=" + usbApi.fd);
            ret = finger.LIVESCAN_Init_Android(filedescription);
            Log.d(TAG, "open:ret=" + ret);
            if (ret > 0) {
                //"init ok
            } else {
                //"init fail

            }
            ret = finger.LIVESCAN_EndCapture(0);
            Log.d(TAG, "open:LIVESCAN_EndCapture ret=" + ret);
            ret = finger.LIVESCAN_BeginCapture(0);
            Log.d(TAG, "open:LIVESCAN_BeginCapture ret=" + ret);
            if (ret > 0) {
                //begin ok
            } else {
                //"begin fail

            }
            mConSample.inited = true;

            ret = finger.LIVESCAN_GetFPBmpDataDelete(0, sampleimage);
            Log.d(TAG, "open:LIVESCAN_GetFPBmpDataDelete ret=" + ret);
            for (int i = 0; i < (256 * 360 + 1078) / 2; i++) {
                bmpdelete[2 * i + 1] = (byte) (sampleimage[i] >> 8 & 0xff);
                bmpdelete[2 * i] = (byte) (sampleimage[i] & 0xff);
            }
            Log.d(TAG, "open:bmpdelete =" + "over");
//            File mFile_cal = new File(filename_cal);
//            Log.d(TAG, "open:mFile_cal =" + "mFile_cal");
//            if (mFile_cal.exists()) {
//                mFile_cal.delete();
//            }
//            Log.d(TAG, "open:exists =" + "delete");
//            try {
//                mandroidbmp.save_bmp(filename_cal, bmpdelete);
//                Log.d(TAG, "open:save_bmp =" + "mandroidbmp");
//            } catch (IOException e) {
//                e.printStackTrace();
//
//            }

//            Bitmap bm_cal = BitmapFactory.decodeFile(filename_cal);
            //bm_cal指纹图
            Log.d(TAG, "open:bm_cal =" + "bm_cal == null");
            if (ret > 0) {
                //"sample background ok

            } else {
                //"sample background fail

            }
            Log.d(TAG, "open:ret =" + ret);

        } else {
            //不能点
        }
        message = Base64.encodeToString(bmpdelete, Base64.DEFAULT);
        Log.d(TAG, "open: =" + "end");
        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }


    private void close(String message, CallbackContext callbackContext) {

        //真要关闭就得下电。
        ret = finger.LIVESCAN_EndCapture(0);
        Log.d(TAG, "LIVESCAN_EndCapture: = " + ret);
        ret = finger.LIVESCAN_Close();
        Log.d(TAG, "LIVESCAN_Close: = " + ret);
        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void calibration(String message, CallbackContext callbackContext) {
        Log.d(TAG, "calibration:" + "start");
        ret = finger.LIVESCAN_Cal();
        Log.d(TAG, "calibration:ret" + "LIVESCAN_Cal" + ret);
        if (ret > 0) {
            //"Calibration ok
        } else {
            //"Calibration fail
        }

        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void collect(String message, CallbackContext callbackContext) {
        //String filename = bmpfilepath + "/finger.bmp";
        //String filename_cal = bmpfilepath + "/cal.bmp";
        Log.d(TAG, "collect=" + "start");
        ret = finger.LIVESCAN_GetFPBmpData(0, sampleimage);
        Log.d(TAG, "collect LIVESCAN_GetFPBmpData = " + ret);
        for (int i = 0; i < (256 * 360 + 1078) / 2; i++) {
            bmpdelete[2 * i + 1] = (byte) (sampleimage[i] >> 8 & 0xff);
            bmpdelete[2 * i] = (byte) (sampleimage[i] & 0xff);
        }
        Log.d(TAG, "collect bmpdelete = " + "end");
        int image_length = bmpdelete.length;
//        File mFile = new File(filename);
//        Log.d(TAG, "collect mFile = " + "mFile");
//        if (mFile.exists()) {
//            mFile.delete();
//        }
//        Log.d(TAG, "collect mFile = " + "exists");
//        try {
//            mandroidbmp.save_bmp(filename, bmpdelete);
//            Log.d(TAG, "collect save_bmp = " + "mandroidbmp");
//        } catch (IOException e) {
//            Log.d(TAG, "collect IOException = " + e.getMessage());
//            e.printStackTrace();
//        }

//        Bitmap bm = BitmapFactory.decodeFile(filename);
        //bm指纹图
        Log.d(TAG, "collect decodeFile = " + "bm");
        if (ret > 0) {
            //"sample fingermap ok\n");
        } else {
            //"sample fingermap fail\n");
        }
        message = Base64.encodeToString(bmpdelete, Base64.DEFAULT);
        Log.d(TAG, "collect end = " + ret);
        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void continuousCollect(String message, CallbackContext callbackContext) {
        this.callbackContext = callbackContext;
        PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT);
        result.setKeepCallback(true);
        this.callbackContext.sendPluginResult(result);

        Log.d(TAG, "continuousCollect=" + "start");
        mConSample.runing = true;
        Log.d(TAG, "continuousCollect=" + "end");
        //h5端传给我什么参数，此处再传回去
//        if (message != null && message.length() > 0) {
//            //callbackContext.success(message);
//            callback(PluginResult.Status.OK, true, message);
//        } else {
//            //callbackContext.error("Expected one non-empty string argument.");
//            callErrorback("Expected one non-empty string argument.");
//        }
    }

    private void stopContinuousCollect(String message, CallbackContext callbackContext) {
        Log.d(TAG, "stopContinuousCollect:" + "start");
        mConSample.close();
        Log.d(TAG, "stopContinuousCollect" + "over");

        //h5端传给我什么参数，此处再传回去
        if (message != null && message.length() > 0) {
            callbackContext.success(message);
        } else {
            callbackContext.error("Expected one non-empty string argument.");
        }
    }

    private void callback(final PluginResult.Status state,
                          final boolean isKeepCallback, final String data) {
        PluginResult result;
        if (data != null) {
            result = new PluginResult(state, data);
        } else {
            result = new PluginResult(state);
        }
        result.setKeepCallback(isKeepCallback);
        callbackContext.sendPluginResult(result);
        Log.d(TAG, "callbackContext.isFinished():" + callbackContext.isFinished());
    }

    private void callErrorback(String error) {
        PluginResult result;
        result = new PluginResult(PluginResult.Status.ERROR, error);
        result.setKeepCallback(false);
        this.callbackContext.sendPluginResult(result);
    }


    //初始化相关
    private static final int REQUEST_CODE = 1;

    public void verifyPermission(Context context) {
        try {
            int permission = ActivityCompat.checkSelfPermission(cordova.getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // We don't have permission so prompt the user
                ActivityCompat.requestPermissions(
                        cordova.getActivity(),
                        PERMISSIONS_STORAGE,
                        REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        Log.d("Permission", "requestCode = " + requestCode);
        if (requestCode == REQUEST_EXTERNAL_STORAGE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 权限被授予，继续执行相关操作
                Log.d("Permission", "Storage permission ok");
            } else {
                // 权限被拒绝，处理相应逻辑
                Log.e("Permission", "Storage permission denied");
            }
        }
    }

    public class MessageHandler extends Handler {
        public MessageHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    //msg.obj.toString() 指纹图像信息
                    msg.obj.toString();
                    Log.d(TAG, "1 msg.obj.toString()=" + (msg.obj != null));

                    break;
                case 3:
                    //文字信息
                    //msg.obj.toString()
                    Log.d(TAG, "3 msg.obj.toString()=" + msg.obj.toString());
                    //文字信息
                    break;
                case 36:
                    //没有
                    if (msg.obj == null) {
                        Log.d(TAG, "36 msg.obj = null");
                        return;
                    }
                    Drawable mDrawable = new BitmapDrawable(mContext.getResources(), (Bitmap) msg.obj);
                    Log.d(TAG, "36 msg.obj = mDrawable");
                    //mDrawable  指纹图
                    break;
                case 101:
                    //没有
                    Log.d(TAG, "101 msg.obj");
                    break;

            }
        }

    }

    private final ConSample.SampleListener mSampleListener = new ConSample.SampleListener() {

        @Override
        public void onResp(String info) {
            if (info == null) {

            } else if ("dataerror".equals(info)) {
                Log.d(TAG, "onResp mSampleListener = dataerror");
                //错误
                callErrorback("onResp mSampleListener = dataerror");
            }
        }

        @Override
        public void onRespBytes(byte[] info) {
            if (info == null) {

            } else {
                //有指纹图
                callback(PluginResult.Status.OK, true, Base64.encodeToString(info, Base64.DEFAULT));
                Log.d(TAG, "onResp mSampleListener = info");
            }
        }

    };

    //====================操作上下电-----------------------
    /**
     * DMR模块GPIO控制
     */
    private DeviceControlSpd DevCtrl;


    private final String HOST = "/sys/hs_typec_switch/hs_enable_host_ctrl/";

    public void Power(String path, String msg) throws IOException {
        try {
            Log.d("xuyanshuai", "PowerOnOff");
            BufferedWriter CtrlFile = new BufferedWriter(new FileWriter(path, false));
            CtrlFile.write(msg);
            CtrlFile.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //====================上电-----------------------
    public void initPower() {
        try {
            //, 41, 43, 40,33, 34,
            DevCtrl = new DeviceControlSpd(DeviceControlSpd.PowerType.NEW_MAIN_FG);
            DevCtrl.newFgSetGpioOn(41);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(43);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(33);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(40);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(34);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            Log.d(TAG, "DevCtrl is open DevCtrl = " + DevCtrl);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void initPower6762() {
        try {
            //, 175, 176, 57, 17, 19
            DevCtrl = new DeviceControlSpd(DeviceControlSpd.PowerType.NEW_MAIN_FG);
            DevCtrl.newFgSetGpioOn(175);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(176);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(17);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            DevCtrl.newFgSetGpioOn(19);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.newFgSetGpioOn(57);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            Log.d(TAG, "DevCtrl is open DevCtrl = " + DevCtrl);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void initPowerT7520() {
        try {
            Power(HOST, "1");

            //170 - 64 = 106   171 - 64 = 107   242 - 64 = 178
            DevCtrl = new DeviceControlSpd(DeviceControlSpd.PowerType.ZHANRUI_MAIN);
            DevCtrl.zhanruiSetGpioOn(106);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.zhanruiSetGpioOn(107);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            DevCtrl.zhanruiSetGpioOn(170);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            Log.d(TAG, "DevCtrl is open DevCtrl = " + DevCtrl);

        } catch (Exception e) {
            //throw new RuntimeException(e);
            e.printStackTrace();
        }

    }
    //====================下电-----------------------

    /**
     * 退出程序时关闭设备控制
     */
    public void releaseDMRModule() {

        if (DevCtrl != null) {
            Log.d(TAG, "close dev power");
            try {
                //DevCtrl.PowerOffDevice();
                DevCtrl.newFgSetGpioOff(33);
                DevCtrl.newFgSetGpioOff(34);
                DevCtrl.newFgSetGpioOff(40);
                DevCtrl.newFgSetGpioOff(43);
                DevCtrl.newFgSetGpioOff(41);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public void releaseDMRModule6762() {
//, 175, 176, 57, 19, 17
        if (DevCtrl != null) {
            Log.d(TAG, "close dev power");
            try {
                //DevCtrl.PowerOffDevice();
                DevCtrl.newFgSetGpioOff(17);
                DevCtrl.newFgSetGpioOff(19);
                DevCtrl.newFgSetGpioOff(57);
                DevCtrl.newFgSetGpioOff(176);
                DevCtrl.newFgSetGpioOff(175);

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void releaseT7520Module() {
        try {
            //退出
            Power(HOST, "0");

            DevCtrl.zhanruiSetGpioOff(106);

            DevCtrl.zhanruiSetGpioOff(107);

            DevCtrl.zhanruiSetGpioOff(170);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}